package repository

import (
	"context"
	"errors"

	"github.com/example/video_backend/internal/model"
	"gorm.io/gorm"
)

// VideoRepository 视频仓库接口
type VideoRepository interface {
	Create(ctx context.Context, video *model.Video) error
	GetByID(ctx context.Context, id uint) (*model.Video, error)
	Update(ctx context.Context, video *model.Video) error
	Delete(ctx context.Context, id uint) error
	List(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*model.Video, int64, error)
	IncreaseViews(ctx context.Context, id uint) error
	IncreaseLikesCount(ctx context.Context, id uint) error
	DecreaseLikesCount(ctx context.Context, id uint) error
	IncreaseCommentsCount(ctx context.Context, id uint) error
	DecreaseCommentsCount(ctx context.Context, id uint) error
	// 检查分类下是否有视频
	HasVideosByCategory(ctx context.Context, categoryID uint) (bool, error)
}

// videoRepository 实现VideoRepository接口
type videoRepository struct {
	db *gorm.DB
}

// NewVideoRepository 创建视频仓库实例
func NewVideoRepository(db *gorm.DB) VideoRepository {
	return &videoRepository{db: db}
}

// Create 创建视频
func (r *videoRepository) Create(ctx context.Context, video *model.Video) error {
	return r.db.WithContext(ctx).Create(video).Error
}

// GetByID 根据ID获取视频
func (r *videoRepository) GetByID(ctx context.Context, id uint) (*model.Video, error) {
	var video model.Video
	err := r.db.WithContext(ctx).First(&video, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &video, nil
}

// Update 更新视频
func (r *videoRepository) Update(ctx context.Context, video *model.Video) error {
	return r.db.WithContext(ctx).Save(video).Error
}

// Delete 删除视频
func (r *videoRepository) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Delete(&model.Video{}, id).Error
}

// /dev/mmcblk1p1: LABEL="android" UUID="677F-B016" BLOCK_SIZE="512" TYPE="exfat" PTTYPE="dos"
// List 分页获取视频列表
func (r *videoRepository) List(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*model.Video, int64, error) {
	var videos []*model.Video
	var total int64

	query := r.db.WithContext(ctx).Model(&model.Video{})

	// 应用过滤条件
	for key, value := range filters {
		query = query.Where(key, value)
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset((page - 1) * pageSize).Limit(pageSize).Order("created_at desc").Find(&videos).Error; err != nil {
		return nil, 0, err
	}

	return videos, total, nil
}

// IncreaseViews 增加视频观看次数
func (r *videoRepository) IncreaseViews(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&model.Video{}).Where("id = ?", id).UpdateColumn("views", gorm.Expr("views + 1")).Error
}

// IncreaseLikesCount 增加视频点赞数
func (r *videoRepository) IncreaseLikesCount(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&model.Video{}).Where("id = ?", id).UpdateColumn("likes_count", gorm.Expr("likes_count + 1")).Error
}

// DecreaseLikesCount 减少视频点赞数
func (r *videoRepository) DecreaseLikesCount(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&model.Video{}).Where("id = ?", id).UpdateColumn("likes_count", gorm.Expr("likes_count - 1")).Error
}

// IncreaseCommentsCount 增加视频评论数
func (r *videoRepository) IncreaseCommentsCount(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&model.Video{}).Where("id = ?", id).UpdateColumn("comments_count", gorm.Expr("comments_count + 1")).Error
}

// DecreaseCommentsCount 减少视频评论数
func (r *videoRepository) DecreaseCommentsCount(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&model.Video{}).Where("id = ?", id).UpdateColumn("comments_count", gorm.Expr("comments_count - 1")).Error
}

// HasVideosByCategory 检查分类下是否有视频
func (r *videoRepository) HasVideosByCategory(ctx context.Context, categoryID uint) (bool, error) {
	var count int64
	err := r.db.WithContext(ctx).Model(&model.Video{}).Where("category_id = ?", categoryID).Count(&count).Error
	if err != nil {
		return false, err
	}
	return count > 0, nil
}
